package cn.monkey.transport.netty.duplex;

import cn.monkey.transport.core.Exchange;
import cn.monkey.transport.core.ExchangeFactory;
import cn.monkey.transport.netty.NettyExchange;
import cn.monkey.transport.netty.NettyExchangeFactory;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;

import java.util.Optional;

public abstract class AbstractDuplexExchangeFactory<C, NE extends NettyExchange, E extends Exchange, DE extends DuplexExchange>
        implements DuplexExchangeFactory<Channel, DE> {
    public static final AttributeKey<?> EXCHANGE_CONFIG_ATTRIBUTE_KEY = AttributeKey.newInstance("EXCHANGE_CONFIG");
    protected final NettyExchangeFactory<NE> nettyExchangeFactory;
    protected final ExchangeFactory<C, E> exchangeFactory;
    protected C exchangeConfig;
    public AbstractDuplexExchangeFactory(NettyExchangeFactory<NE> nettyExchangeFactory,
                                         ExchangeFactory<C, E> exchangeFactory) {
        this.nettyExchangeFactory = nettyExchangeFactory;
        this.exchangeFactory = exchangeFactory;
    }

    public void setExchangeConfig(C exchangeConfig) {
        this.exchangeConfig = exchangeConfig;
    }

    @Override
    @SuppressWarnings("unchecked")
    public DE apply(String s, Exchange exchange, Channel channel) {
        NE nettyExchange = this.nettyExchangeFactory.apply(s, exchange, channel);
        C c = Optional.ofNullable(this.exchangeConfig).orElse((C) channel.attr(EXCHANGE_CONFIG_ATTRIBUTE_KEY).get());
        E e = this.exchangeFactory.apply(s, exchange, c);
        return this.newExchange(nettyExchange, e);
    }

    protected abstract DE newExchange(NE nettyExchange, E e);
}
